import { BufferStats, ReadOptions, OutputResult } from '../types';

interface DataChunk {
  index: number;
  content: string;
  timestamp: Date;
}

export class OutputBuffer {
  private chunks: DataChunk[] = [];
  private chunkCounter: number = 0;
  private maxChunks: number;
  private maxTotalSize: number;
  private currentTotalSize: number = 0;

  constructor(maxChunks: number = 1000, maxTotalSize: number = 10 * 1024 * 1024) {
    this.maxChunks = maxChunks;
    this.maxTotalSize = maxTotalSize;
  }

  append(data: string): void {
    if (!data) return;

    const chunk: DataChunk = {
      index: this.chunkCounter++,
      content: data,
      timestamp: new Date()
    };

    this.chunks.push(chunk);
    this.currentTotalSize += Buffer.byteLength(data, 'utf8');

    while (this.chunks.length > this.maxChunks || this.currentTotalSize > this.maxTotalSize) {
      const removed = this.chunks.shift();
      if (removed) {
        this.currentTotalSize -= Buffer.byteLength(removed.content, 'utf8');
      }
    }
  }

  read(options: ReadOptions = {}): OutputResult {
    const {
      since = 0,
    } = options;

    let chunks = this.chunks.filter(c => c.index >= since);

    if (chunks.length === 0) {
      return {
        output: '',
        totalLines: this.chunks.length,
        nextReadFrom: this.chunkCounter,
        hasMore: false,
        truncated: false,
        stats: {
          totalBytes: 0,
          estimatedTokens: 0,
          linesShown: 0,
          linesOmitted: 0
        }
      };
    }

    const output = chunks.map(c => c.content).join('');
    const totalBytes = Buffer.byteLength(output, 'utf8');
    const estimatedTokens = Math.ceil(totalBytes / 4);

    return {
      output,
      totalLines: this.chunks.length,
      nextReadFrom: this.chunkCounter,
      hasMore: false,
      truncated: false,
      stats: {
        totalBytes,
        estimatedTokens,
        linesShown: chunks.length,
        linesOmitted: 0
      }
    };
  }

  getStats(): BufferStats {
    const totalBytes = this.currentTotalSize;
    const estimatedTokens = Math.ceil(totalBytes / 4);

    return {
      totalLines: this.chunks.length,
      totalBytes,
      estimatedTokens,
      bufferSize: this.maxChunks,
      oldestLine: this.chunks.length > 0 ? this.chunks[0].index : 0,
      newestLine: this.chunks.length > 0 ? this.chunks[this.chunks.length - 1].index : 0
    };
  }

  clear(): void {
    this.chunks = [];
    this.chunkCounter = 0;
    this.currentTotalSize = 0;
  }
}
